<?php

namespace App\Service\OpenShop\SiteLocation;

use App\Enums\BaseErrorCode;
use App\Enums\OpenShop\InvestmentPromotion\SiteLocationEnum;
use App\Enums\OpenShop\MissionTemplateEnum;
use App\Exceptions\Custom\ResponseHttpException;
use App\Models\Common\ConfigModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderPermissionAnchorModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationExamineLogModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationModel;
use App\Service\OpenShop\Feishu\BaseService;
use App\Service\OpenShop\User\RmsUserService;
use App\Service\OpenShop\Wap\SignOrderService;
use App\Service\Rms\ShopService;
use Ballen\Distical\Calculator as DistanceCalculator;
use Ballen\Distical\Entities\LatLong;
use Carbon\Carbon;
use Guanguans\Notify\Factory;

class PlaceHolderSiteLocationService extends BaseService
{
    private $orderNo;

    public function __construct(?string $orderNo)
    {
        $this->orderNo = $orderNo;
    }

    /**
     * 指派开发经理的时候添加用户信息
     *
     * @param string $orderNo
     * @param array $saveData
     */
    public function manageSavePlaceholder(array $saveData, bool $forceUpdate = false): array
    {
        $orderModel = OpenShopSignOrderModel::query()
                                            ->with('progressRel')
                                            ->where('orderNo', $this->orderNo)
                                            ->first();

        // 判断是否已经确认完选址
        if (!$forceUpdate && $orderModel->progressRel->nowStepStatus > MissionTemplateEnum::STEP_STATUS_5) {
            throw new ResponseHttpException(BaseErrorCode::$LOCATION_PLACEHOLDER_NO_EDIT_TIME);
        }

        $orderModel->isPlaceholder = $saveData['isPlaceholder'] ?? OpenShopSignOrderModel::IS_PLACEHOLDER_NO;
        $orderModel->save();

        $saveData['source']        = OpenShopSiteLocationModel::SOURCE_PLACEHOLDER;
        $saveData['orderNo']       = $this->orderNo;
        $saveData['mainProcessId'] = $orderModel->mainProcessId;

        $rmsInfo                           = getRmsUserInfoByAuth();
        $saveData['developConsultantName'] = $rmsInfo->username;
        $saveData['developConsultantId']   = $rmsInfo->id;

        $result = [];

        if ($orderModel->isPlaceholder) {
            // 判断当前订单状态
            if ($orderModel->progressRel->nowStepStatus <= MissionTemplateEnum::STEP_STATUS_3) {
                $saveData['siteStatus'] = OpenShopSiteLocationModel::SITE_STATUS_0;
            } else {
                $saveData['siteStatus'] = OpenShopSiteLocationModel::SITE_STATUS_10;
            }
            $result = $this->savePlaceholder($saveData);
        }

        if ($orderModel->isPlaceholder && $saveData['siteStatus'] == OpenShopSiteLocationModel::SITE_STATUS_10) {
            // 添加审核通知
            $placeholderNotify = new SendFsService($this->orderNo, OpenShopSiteLocationModel::SOURCE_PLACEHOLDER);
            $provinceInfo      = $this->getProvinceInfo();
            $placeholderNotify->sendAuditNotify([$provinceInfo['operationUid']]);

        }

        return $result;
    }

    /**
     * 添加更新预占点位
     *
     * @param array $saveData
     * @return array
     */
    private function savePlaceholder(array $saveData): array
    {
        try {
            if (!is_numeric($saveData['placeholderTime'])) {
                $saveData['placeholderTime'] = strtotime($saveData['placeholderTime'] . ' 23:59:59');
            }
            $result = OpenShopSiteLocationModel::query()->updateOrCreate([
                'orderNo'       => $saveData['orderNo'],
                'mainProcessId' => $saveData['mainProcessId'],
                'source'        => $saveData['source']
            ], collect($saveData)->except(['orderNo', 'mainProcessId', 'source'])->toArray());
            // 获取附近门店信息
            self::updateNearByInfo($saveData['cityCode'] ?? 0, explode('-', ($saveData['cityArea'] ?? ''))[1] ?? '');
            return $result->toArray();
        } catch (\Exception $exception) {
            handleException($exception);
            return [];
        }
    }

    /**
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     */

    private static $placeholderInfo = null;

    public function getPlaceholderInfo(bool $refresh = false)
    {
        if ($refresh || empty(self::$placeholderInfo)) {
            self::$placeholderInfo = OpenShopSiteLocationModel::query()
                                                              ->where('source',
                                                                  OpenShopSiteLocationModel::SOURCE_PLACEHOLDER)
                                                              ->where('orderNo', $this->orderNo)
                                                              ->first();

        }
        return self::$placeholderInfo;
    }

    /**
     * @param int $id
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     */
    public static function getPlaceholderById(int $id)
    {
        return OpenShopSiteLocationModel::query()
                                        ->where('id', $id)
                                        ->first();
    }

    /**
     * 更新附近点位,门店信息
     *
     * @param string $orderNo
     */
    public function updateNearByInfo(int $cityCode = 0, string $city = '')
    {
        $info = $this->getPlaceholderInfo(true);
        // 获取附近门店信息
        $nearByShop = GuanyuanDataService::closestShop($info->latitude, $info->longitude, $city);
        // 获取附近点位信息
        $placeholderList = OpenShopSiteLocationModel::query()
                                                    ->where('source', OpenShopSiteLocationModel::SOURCE_PLACEHOLDER)
                                                    ->where('placeholderTime', '>', time())
                                                    ->where('siteStatus', OpenShopSiteLocationModel::SITE_STATUS_4)
                                                    ->when($cityCode, function ($query) use ($cityCode) {
                                                        $query->where('cityCode', $cityCode);
                                                    })
                                                    ->get();

        if (!empty($nearByShop) && !empty($nearByShop['code'])) {
            $info->nearbyShopCode = $nearByShop['code'];
            $info->nearbyRange    = $nearByShop['distance'];
        }

        $minNearByPlaceholderInfo = [
        ];
        foreach ($placeholderList as $placeholder) {
            try {
                $distance = (new DistanceCalculator(
                    new LatLong($info->latitude, $info->longitude),
                    new LatLong($placeholder->latitude, $placeholder->longitude)
                ))->get()->asKilometres();
            } catch (\Exception $e) {
                $distance = 0;
            }

            if (empty($minNearByPlaceholderInfo)) {
                $minNearByPlaceholderInfo = [
                    'nearbyPlaceHolderId'    => $placeholder->id,
                    'nearbyPlaceHolderRange' => $distance
                ];
            }

            if (bccomp($minNearByPlaceholderInfo['nearbyPlaceHolderRange'], $distance) == 1) {
                $minNearByPlaceholderInfo = [
                    'nearbyPlaceHolderId'    => $placeholder->id,
                    'nearbyPlaceHolderRange' => $distance
                ];
            }
        }

        if (!empty($minNearByPlaceholderInfo)) {
            $info->nearbyPlaceHolderId    = $minNearByPlaceholderInfo['nearbyPlaceHolderId'];
            $info->nearbyPlaceHolderRange = $minNearByPlaceholderInfo['nearbyPlaceHolderRange'];
        } else {
            $info->nearbyPlaceHolderId    = 0;
            $info->nearbyPlaceHolderRange = 0;
        }

        $info->save();
    }

    public function returnFrontEnd()
    {
        if (empty($this->getPlaceholderInfo())) {
            return [];
        }

        $data = $this->getPlaceholderInfo()->toArray();

        $nearbyShopName        = empty($data['nearbyShopCode']) ? '' : ShopService::getShopNameByCode($data['nearbyShopCode']) ?? '';
        $nearbyPlaceHolderName = OpenShopSiteLocationModel::getShopNameByIdNearByPlaceholderId($data['nearbyPlaceHolderId']);

        $result = [
            'info' => [
                'title' => '点位信息',
                'data'  => [
                    self::formUnit('siteAddress', 'map', '点位定位', $data['siteAddress'] ?? '', [], ['required' => true]),
                    self::formUnit('siteStatus', 'select-old', '状态', $data['siteStatus'] ?? 0,
                        [
                            'options'  => SiteLocationEnum::getOptionsByConst(OpenShopSiteLocationModel::PLACEHOLDER_SITE_STATUS_TEXT),
                            'disabled' => true
                        ],
                        ['required' => true]),
                    self::formUnit('cityArea', 'address', '省市区', $data['cityArea'], [
                        'disabled' => true
                    ], ['required' => true]),
                    self::formUnit('address', 'textarea', '详细地址', $data['address'], [], ['required' => true]),
                    self::formUnit('longitude', 'text', '', $data['longitude'], ['display' => false], []),
                    self::formUnit('latitude', 'text', '', $data['latitude'], ['display' => false], []),
                    self::formUnit('provinceCode', 'text', '', $data['provinceCode'], ['display' => false], []),
                    self::formUnit('cityCode', 'text', '', $data['cityCode'], ['display' => false], []),
                    self::formUnit('areaCode', 'text', '', $data['areaCode'], ['display' => false], []),
                ]
            ],
            'near' => [
                'title' => '附近门店',
                'data'  => [
                    self::formUnit('nearbyShopName', 'text', '附近门店', $nearbyShopName, ['disabled' => true],
                        ['required' => true]),
                    self::formUnit('nearbyRange', 'number', '附近门店距离', $data['nearbyRange'],
                        ['unit' => 'km', 'disabled' => true],
                        ['required' => true]),
                    self::formUnit('nearbyPlaceHolderName', 'text', '附近点位', $nearbyPlaceHolderName,
                        ['disabled' => true],
                        ['required' => true]),
                    self::formUnit('nearbyPlaceHolderRange', 'number', '附近点位距离', $data['nearbyPlaceHolderRange'],
                        ['unit' => 'km', 'disabled' => true],
                        ['required' => true]),
                    self::formUnit('placeholderTime', 'date', '到期时间', date('Y-m-d', $data['placeholderTime']), [],
                        ['required' => true])
                ]
            ]
        ];

        return array_values($result);
    }

    public static function formUnit(
        string $field,
        string $inputType,
        string $text,
        $value,
        array $customAttributes = [],
        array $validate = []
    ): array {
        return [
            'field'            => $field,
            'inputType'        => $inputType,
            'text'             => $text,
            'value'            => $value,
            'customAttributes' => $customAttributes,
            'validate'         => $validate
        ];
    }

    public function audit(array $authUser, int $status, string $content)
    {
        if (!$this->checkAuditAccess($authUser['userId'] ?? 0)) {
            throw new ResponseHttpException(BaseErrorCode::$LOCATION_PLACEHOLDER_AUDIT_NO_ACCESS);
        }
        // 判断审核角色
        switch ($this->getPlaceholderInfo()->siteStatus) {
            case OpenShopSiteLocationModel::SITE_STATUS_3:
            case OpenShopSiteLocationModel::SITE_STATUS_10:
                // 省总审核
                $position = OpenShopSiteLocationExamineLogModel::POSITION_PROVINCE_EXAMINE;
                break;
            case OpenShopSiteLocationModel::SITE_STATUS_11:
                // 超管审核
                $position = OpenShopSiteLocationExamineLogModel::POSITION_GENERAL_EXAMINE;
                break;
            default:
                throw new ResponseHttpException(BaseErrorCode::$LOCATION_PLACEHOLDER_NO_AUDIT_TIME);
        }

//        // 判断是否审核
//        $statusOkExist = OpenShopSiteLocationExamineLogModel::query()
//                                                            ->where("source",
//                                                                OpenShopSiteLocationModel::SOURCE_PLACEHOLDER)
//                                                            ->where('orderNo', $this->orderNo)
//                                                            ->where('position', $position)
//                                                            ->where('status',
//                                                                OpenShopSiteLocationExamineLogModel::STATUS_OK)
//                                                            ->exists();

//        if (!$statusOkExist) {
        OpenShopSiteLocationExamineLogModel::query()->create([
            'source'   => OpenShopSiteLocationModel::SOURCE_PLACEHOLDER,
            'orderNo'  => $this->orderNo,
            'position' => $position,
            'content'  => $content,
            'status'   => $status,
        ]);

        $placeholderInfo = $this->getPlaceholderInfo();

        $siteStatus = $this->getPlaceholderInfo()->siteStatus;
        switch ($status) {
            case OpenShopSiteLocationExamineLogModel::STATUS_OK:
                switch ($siteStatus) {
                    case OpenShopSiteLocationModel::SITE_STATUS_10:
                        // 省总审核
                        $placeholderInfo->siteStatus = OpenShopSiteLocationModel::SITE_STATUS_4;
                        break;
                    case OpenShopSiteLocationModel::SITE_STATUS_11:
                        // 超管审核
                        $placeholderInfo->siteStatus = OpenShopSiteLocationModel::SITE_STATUS_4;
                        break;
                    default:
                        throw new ResponseHttpException(BaseErrorCode::$LOCATION_PLACEHOLDER_NO_AUDIT_TIME);
                }
                break;
            case OpenShopSiteLocationExamineLogModel::STATUS_REFUSE:
                switch ($siteStatus) {
                    case OpenShopSiteLocationModel::SITE_STATUS_10:
                    case OpenShopSiteLocationModel::SITE_STATUS_11:
                        // 超管审核
                        $placeholderInfo->siteStatus = OpenShopSiteLocationModel::SITE_STATUS_3;
                        break;
                    default:
                        throw new ResponseHttpException(BaseErrorCode::$LOCATION_PLACEHOLDER_NO_AUDIT_TIME);
                }
                break;
        }

        $placeholderInfo->save();

        $placeholderNotify = new SendFsService($this->orderNo);
        switch ($status) {
            case OpenShopSiteLocationExamineLogModel::STATUS_OK:
                switch ($siteStatus) {
                    case OpenShopSiteLocationModel::SITE_STATUS_10:
                    case OpenShopSiteLocationModel::SITE_STATUS_11:
                        // 省总审核
//                        $sitePlaceholderManage = ConfigModel::getManager(ConfigModel::SITE_PLACEHOLDER_ADMIN);
////                        $placeholderNotify->sendAuditHandleNotify($sitePlaceholderManage); // 赤瞳大黄蜂
//                        $placeholderNotify->sendAuditNotify($sitePlaceholderManage);
                        $placeholderNotify->sendAuditHandleNotify([
                            $this->getProvinceId(),
                            $this->getInvestmentManagerId()
                        ]);
                }
                break;
            case OpenShopSiteLocationExamineLogModel::STATUS_REFUSE:
                switch ($siteStatus) {
                    case OpenShopSiteLocationModel::SITE_STATUS_10:
                    case OpenShopSiteLocationModel::SITE_STATUS_11:
                        // 超管审核
                        $placeholderNotify->sendAuditHandleNotify([
                            $this->getProvinceId(),
                            $this->getInvestmentManagerId()
                        ]);
                        break;
                    default:
                        throw new ResponseHttpException(BaseErrorCode::$LOCATION_PLACEHOLDER_NO_AUDIT_TIME);
                }
                break;
        }


        // 最终审核通过之后需要做的事情
        if ($placeholderInfo->siteStatus == OpenShopSiteLocationModel::SITE_STATUS_4) {
            // TODO
        }
//        }

    }

    /**
     * 校验审核权限
     *
     * @param int $nowUserId
     * @return bool
     */
    public function checkAuditAccess(int $nowUserId)
    {
        $isCan                 = false;
        $sitePlaceholderManage = ConfigModel::getManager(ConfigModel::SITE_PLACEHOLDER_ADMIN);

        switch ($this->getPlaceholderInfo()->siteStatus) {
            case OpenShopSiteLocationModel::SITE_STATUS_10:
                $provinceInfo = $this->getProvinceInfo();
                // 是否省总
                if ($nowUserId == $provinceInfo['operationUid']) {
                    $isCan = true;
                    break;
                }
                break;
            case OpenShopSiteLocationModel::SITE_STATUS_11:
                // 是否超管
                if (in_array($nowUserId, $sitePlaceholderManage)) {
                    $isCan = false;
                    break;
                }
                break;
        }
        return $isCan;
    }

    /**
     * 校验编辑权限
     *
     * @param int $nowUserId
     * @return bool
     */
    public function checkEditAccess(int $nowUserId)
    {
        $isCan                 = false;
        $sitePlaceholderManage = ConfigModel::getManager(ConfigModel::SITE_PLACEHOLDER_ADMIN);

        switch ($this->getPlaceholderInfo()->siteStatus) {
            case OpenShopSiteLocationModel::SITE_STATUS_0:
            case OpenShopSiteLocationModel::SITE_STATUS_3:
            case OpenShopSiteLocationModel::SITE_STATUS_10:
                $provinceInfo = $this->getProvinceInfo();
                // 是否省总
                if ($nowUserId == $provinceInfo['operationUid']) {
                    $isCan = true;
                    break;
                }
                // 是否开发
                if ($nowUserId == $this->getInvestmentManagerId()) {
                    $isCan = true;
                    break;
                }
                // 是否超管
                if (in_array($nowUserId, $sitePlaceholderManage)) {
                    $isCan = true;
                    break;
                }
                break;
            case OpenShopSiteLocationModel::SITE_STATUS_11:
                // 是否超管
                if (in_array($nowUserId, $sitePlaceholderManage)) {
                    $isCan = true;
                    break;
                }
                break;
        }
        return $isCan;
    }

    public function getSignOrderInfo()
    {
        return (new SignOrderService($this->orderNo))->getSignOrder();
    }

    public function getInvestmentManagerId(): int
    {
        $permssionOrder = OpenShopSignOrderPermissionAnchorModel::query()
                                                                ->where('orderNo', $this->orderNo)
                                                                ->first();

        return $permssionOrder->localInvestmentManagerId ?? 0;
    }

    /**
     * 省总 ID
     *
     * @return mixed
     */
    public function getProvinceId()
    {
        return $this->getProvinceInfo()['operationUid'];
    }

    /**
     * 省总信息
     *
     * @return mixed
     */
    public function getProvinceInfo()
    {
        $permssionOrder = OpenShopSignOrderPermissionAnchorModel::query()
                                                                ->where('orderNo', $this->orderNo)
                                                                ->first()
                                                                ->getProvinceInfo();

        return $permssionOrder;
    }

    public function getAuditHistory(): array
    {
        $result = [];

        $list = OpenShopSiteLocationExamineLogModel::query()
                                                   ->where("source",
                                                       OpenShopSiteLocationModel::SOURCE_PLACEHOLDER)
                                                   ->where('orderNo', $this->orderNo)
                                                   ->orderBy('id', 'desc')
                                                   ->get();

        $body      = RmsUserService::getRmsUserInfoByUserIds($list->pluck('createdByUid')->toArray())['data'] ?? [];
        $userNames = array_column($body, 'username', 'id');

        foreach ($list as $value) {
            $result[] = [
                'content'     => $value['content'],
                'createdTime' => $value->createdAt->toDateTimeString(),
                'status'      => $value['status'],
                'statusText'  => OpenShopSiteLocationExamineLogModel::STATUS_MAPPING[$value['status']] ?? '',
                'type'        => OpenShopSiteLocationExamineLogModel::SOURCE_MAPPING[$value['source']] ?? '',
                'userName'    => $userNames[$value['createdByUid']] ?? ''
            ];
        }

        return $result;
    }

    /**
     * 清除当前预占点位
     *
     * @param string $orderNo
     */
    public function clearPlaceHolder()
    {
        OpenShopSignOrderModel::query()->where('orderNo', $this->orderNo)->update(
            [
                'isPlaceholder' => OpenShopSignOrderModel::IS_PLACEHOLDER_NO
            ]
        );

        // 清楚
        OpenShopSiteLocationModel::query()
                                 ->where('source', OpenShopSiteLocationModel::SOURCE_PLACEHOLDER)
                                 ->where('orderNo', $this->orderNo)
                                 ->update([
                                     'nearbyPlaceHolderId'    => 0,
                                     'nearbyPlaceHolderRange' => 0,
                                     'placeholderTime'        => 0
                                 ]);
    }

}
